package starfield.mod;

import starfield.modpack.Modpack;
import starfield.util.JSONUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipFile;
import org.apache.commons.io.IOUtils;
import org.json.simple.JSONObject;
import starfield.Metadata;
import starfield.ParsingException;

public class Mod {
	private static final String FILENAME_CONFIG = "mod.config";
	public static final String EXTENSION = "sbm";
	public static final String ASSETS_DIRECTORY_NAME = "assets";
	public static final String KEY_NAME = "name";
	public static final String KEY_GAME_VERSION = "version";
	public static final String KEY_ASSETS_PATH = "path";
	
	protected Modpack modpack;
	protected String name;
	protected String gameVersion;
	protected String assetsPath;
	protected Metadata metadata;
	
	private Mod(Modpack modpack, String name) {
		this.modpack = modpack;
		this.name = name;
		modpack.getMods().add(this);
	}
	
	public static Mod load(Modpack modpack, String fileName) throws IOException, ParsingException {
		Mod mod = new Mod(modpack, fileName);
		
		try (ZipFile zip = new ZipFile(mod.getPath())) {
			try (InputStream is = zip.getInputStream(zip.getEntry(FILENAME_CONFIG))) {
				mod.deserialize(JSONUtils.parseObject(IOUtils.toString(is)));
			}
		}
		
		return mod;
	}
	
	public void delete() throws IOException {
		if (!new File(getPath()).delete()) {
			throw new IOException("Could not delete file '" + name + "'.");
		}
	}
	
	protected void deserialize(JSONObject json) throws ParsingException {
		if (json.containsKey(KEY_NAME)) {
			String configName = JSONUtils.getString(json, KEY_NAME);
			
			if (!configName.equals(name)) {
				throw new ParsingException("Mismatch between specified name and folder name.");
			}
		} else {
			throw new ParsingException("Missing name.");
		}
		
		if (json.containsKey(Metadata.KEY_METADATA)) {
			metadata.deserialize(JSONUtils.getObject(json, Metadata.KEY_METADATA));
		}
	}
	
	protected JSONObject serialize()  {
		JSONObject json = new JSONObject();
		
		json.put(KEY_NAME, name);
		json.put(Metadata.KEY_METADATA, metadata.serialize());
		
		return json;
	}
	
	public String getPath() {
		return modpack.getDirectoryPath() + File.separator + name;
	}
	
	public String toHtmlString() {
		return metadata.toHtmlString();
	}
	
	public String getDisplayName() {
		if (metadata.getTitle() != null) {
			return metadata.getTitle();
		} else {
			return name;
		}
	}
	
	public Modpack getModpack() {
		return modpack;
	}
	
	public String getName() {
		return name;
	}
	
	public Metadata getMetadata() {
		return metadata;
	}

	public String getGameVersion() {
		return gameVersion;
	}

	public void setGameVersion(String gameVersion) {
		this.gameVersion = gameVersion;
	}

	public String getAssetsPath() {
		return assetsPath;
	}

	public void setAssetsPath(String assetsPath) {
		this.assetsPath = assetsPath;
	}
}
